<?

/** Jarva - Dataxi director
 *
 *  This code is licensed under GPL2.
 *  See LICENSE or www.gnu.org for more details.
 *
 *  Entrance to Dataxi. All communication between the client side and Dataxi
 *  traverses trough this routine.
 *
 *  @author Jyry Kuukkanen
 *  $Id: jarva.php 595 2006-04-03 16:00:47Z jyry $
 */

/* Include files needed */
#include_once("xmlrpc.inc");
#include_once("xmlrpcs.inc");

include_once("sodebug.php");
include_once("sostring.php");
include_once("soset.php");
include_once("sogeneric.php");
include_once("sonetwork.php");

include_once("dzgeneric.php");
include_once("dzpoke.php");
include_once("dzitu.php");
include_once("dzconst.php");
include_once("dzlogin.php");
include_once("dzmanager.php");
include_once("dzsession.php");
include_once("dzrpc.php");

/** Define the name for the JavaScript function that will by
   default handle the remote procedure result. */
define(DEFAULT_RPC_RESULT_HANDLER, "handleResult");

/** Delimiter that delimits the results in result string to JavaScript */
define(DZ_ANSWER_DELIMITER, "/dz&");

/** Sundly constants */
define(DZ_RPC_GET_VAR, "rpc");

class jarva {
    /* Debug setting */
    var $DebugLevel;        /** int Debug level */
    var $FormatDebugHtml;   /** bool Will the html tags be added
                             *  to debug messages */
    var $DebugFilter;       /** int Debug filter. */
    var $DebugLogFile;      /** int File to put debug messages */

    var $GetVarSet;         /** soSet Get parameters from the client */
    var $PostVarSet;        /** soSet Post parameters from the client */



    /** constructor
     *  Get the parameters the client sent.
     */
    function jarva() {
        global $_GET;
        global $_POST;

        /* Get the request and user information */
        $this->GetVarSet = new soSet();
        $this->GetVarSet->joinArray($_GET);

        $this->PostVarSet = new soSet();
        $this->PostVarSet->joinArray($_POST);
    } // jarva


    /** Main function. Finds out the request type and serves the whether
     *  the HTTP or xmlrpc request.
     */
    function runJarva() {
        $abort_status = ignore_user_abort(1);

        global $HTTP_RAW_POST_DATA;

        global $soDebugLevel;
        global $soFormatDebugHtml;
        global $soDebugFilter;
        global $soDebugLogFile;

        /* Initialize debug settings */
        $soDebugLevel = $this->DebugLevel;
        $soFormatDebugHtml = $this->FormatDebugHtml;
        $soDebugFilter = $this->DebugFilter;
        $soDebugLogFile = $this->DebugLogFile;

        /* Start capturing output  */
        $buffer = new soOutputBuffer(1);

        /* if incoming call is xmlrpc then launch the server. Otherwise
           we are dealing with a HTTP request. Jarva handles, yeah, yeah. */
        if ($HTTP_RAW_POST_DATA != "") {
            $this->__serveXmlrpc();
        } else {
            if (!$this->GetVarSet->itemExists(DZ_RPC_GET_VAR)) {
                $this->__serveHttp();
            } else {
                $this->__httpRpc();
            };
        }; // if $HTTP_RAW_POST_DATA

        /* End capturing output, compress and output */
        $buffer->finishCapture(1, 1);

        ignore_user_abort($abort_status);
    } // runJarva


    /** Takes care of xmlrpc request
     */
    function __serveXmlrpc() {
        global $xmlrpcString;

        /* Read in the information on remote procedures. */
        $ini_stream = "file://".dzGetMainScriptPath()."/".
                      soExtractVal(basename(__FILE__), ".", -2).".ini";
        /* Create the ini stream and later use it to get the ini information */
        $ini = new soIniData($ini_stream);
        $ini_count = 0;

        /* Dispatch map is constructed here. It will have all the needed
          information on remote functions. */
        $dispatch_map = array();

        /* Collect the information to the dispatch map. */
        while (!$ini->Error) {
            $rpc_function = $ini->getValueSet(DZ_RPC_GET_VAR, $ini_count++);
            $function_name = $ini->getCurrentKeyName();
            $impl_func_name = $rpc_function->getItem("function");
            $impl_file = $rpc_function->getItem("implementation");
            if (!$ini->Error) {
                /* For now, we must include all implementation files, Because we
                don't know yet what function was called. */
                include_once($impl_file);
                $s .= $impl_file."\n";
                $func_data = array("function" => $impl_func_name);

                /* Add found information to dispatch map. */
                $dispatch_map[$function_name] = $func_data;
            } // if (!$ini->Error)
        } // while (!$ini->Error)

        /*  Launch rpc server. */
        $rpc_server = new xmlrpc_server($dispatch_map);
    } //__serveXmlrpc


    /** Takes care of HTTP request
     */
    function __serveHttp() {
        /* Check that teh user has the Dataxi basic frame */
        $SendFrames = !$this->GetVarSet->itemExists("FramesOk");

        /* Get the session Id */
        $user = $this->PostVarSet->getItem(DZRI_USER);
        $password = $this->PostVarSet->getItem(DZRI_PASSWD);
        $session_id = $this->PostVarSet->getItem(DZRI_SESSION);

        /* Create dzPoke that checks the users access rights */
        $poke = new dzPoke($user, $password, $session_id, DZ_ASEMA_REQ);
        $result = $poke->verifyUser();

        if ($result == DZ_POKE_NO_SESSION) {

            /* No session id yet. So Login preces in process or starting */
            $lang = $this->GetVarSet->getItem(DZRI_LANGUAGE);
            if (!$lang) $lang = dzGetIniItem("general", "lang", "app");
            $login_result = dzLogin($this->PostVarSet, $lang, $SendFrames);
            switch ($login_result->Status) {
                case DZ_LOGIN_SEND_FRAMESET:
                case DZ_LOGIN_SEND_LOGIN_SCREEN:
                case DZ_LOGIN_SEND_SESSION_LIST:
                    echo $login_result->Screen;
                    break;

                case DZ_LOGIN_OK:
                    /* Add the session id into parameters */
                    $this->PostVarSet->setItem(DZRI_SESSION,
                                               $login_result->Session);
                    $this->PostVarSet->setItem(DZRI_LANGUAGE, $lang);

                    /* Set flag that the had just logged in */
                    $this->PostVarSet->setItem(DZRI_STARTING, 1);
                    $Session = $login_result->Session;

                    /* Login ok. So allow entering to asema's state machine. */
                    $result = DZVU_USER_CHECK_OK;
                    soDebug("jarva: Using dataxi with session id:".
                            $login_result->Session, SOD_DET);
                    break;
            } // switch ($login_result->Status)
        } // if $result

        if ($result == DZVU_USER_CHECK_OK) {
                /* Login ok proceed to Asema*/
                $asema_result = dzManage($this->PostVarSet);
                switch ($asema_result->Status) {
                    case DZ_MANAGER_ERROR:
                    case DZ_MANAGER_END:
                    case DZ_MANAGER_SEND_SCREEN:
                        echo $asema_result->Screen;
                } // switch ($asema_result)

        } // if $result
    } // __serveHttp


    /** Takes in coming html rpc calls and sends them further using xmlrpc.
     *  Then returns the result back to requester.
     *
     *  This is used when the client sends an rpc request to Dataxi. This
     *  means that not all the data is sent, but just required. Usulally
     *  This technic is used in validy check and thisgs like it.
     */
    function __httpRpc() {
        soDebug("Jarva: Start to serve incoming HTML rpc request", SOD_DET);

        /* Collect the parameters from the var set */
        $params = array();
        $pcount = $this->GetVarSet->getItem("ParCount");
        for ($c = 0; $c < $pcount; $c++) {
            $params[] = $this->GetVarSet->getItem("param".$c);
        } // for

        /* And the result fields */
        $result_fields = array();
        $rcount = $this->GetVarSet->getItem("ResCount");
        for ($c = 0; $c < $rcount; $c++) {
            $result_fields[] = $this->GetVarSet->getItem("result".$c);
        } // for

        /* Create the ity that will carry the parameters to remote procedure */
        $param_itu = new dzItu();
        /* Store parameters and result fields */
        $param_itu->setBlockItem(DZI_CONTROL, DZK_PARAMS, $params);
        $param_itu->setBlockItem(DZI_CONTROL, DZK_RESULT_FIELDS,
                                 $result_fields);


        /* Send the request */
        $function_name = $this->GetVarSet->getItem(DZ_RPC_GET_VAR);
        soDebug("Jarva: function name = $function_name", SOD_DET);
        $result_itu = dzRpcCallParams($function_name, $param_itu);

        /* Error check */
        if (isRpcError($result_itu)) {
            $error_text = getRpcErrorText($result_itu);
        } // if

        /* Produce the html code that sets the result on the calling form */
        /* Get the results in soSet */
        $result_fields = $result_itu->getBlock(DZI_DATA);
        /* Get the name of the JS result handler */
        $result_handler = $this->GetVarSet->getItem("ResultHandler");

        soDebug("Jarva: return data = ".$result_itu->dump("\n"), SOD_DET);
        soDebug("Jarva: result handler = ".$result_handler, SOD_DET);

        /* Send back the result */
        echo $this->produceResultHtml($result_fields,
                                      $result_handler,
                                      $error_text);


    } // __httpRpc


    /** Encode the parameter and construct the piece of javaScript that
     *  delivers the result to calling client.
     *
     *  >$ResultFields:soset Result fields and their values
     *  >$Handler:str Name of the result handler function in JS code
     *  >$ErrorTxt:str   The error message if occurred
     *  <:str    Produced html code
     */
    function produceResultHtml($ResultFields, $Handler, $ErrorTxt = "") {
        /* If handler not given use default */
        if (!$Handler) $Handler = DEFAULT_RPC_RESULT_HANDLER;

        $res_arr = $ResultFields->getAsArray();
        /* Construct the return string. Returned items are separated
          with DZ_ANSWER_DELIMITER delimiter in the string. */
        foreach ($res_arr as $key => $val) {
            /* The set is encoded as follows:
               <key1>=<value1><result_delimiter><key2>=<value2> */
            $param = $key."='".implode("", $val)."'";
            $answer = soJoinStr($answer, DZ_ANSWER_DELIMITER, $param);
        } // foreach

        $output .= "<script language='javascript'><!--\n".
                   "top.opener.".$Handler."(\"". $answer ."\");\n";

        if ($ErrorTxt != "") {
            $output .= "alert('$ErrorTxt');\n";
        } else {
            $output .= "close();\n";
        };

        return $output."// -->\n</script>\n";
    } // produceResultHtml

} // jarva

?>
